{%-set exception %}{{resolver.cpp_get_lib_ns() | join('::')}}::JsonSchemaException{%endset%}
/*! {{Name}} is a wrapper around a {{schema.type}}.
 * The value is limited to a set of enum values.
 {%-if schema.description %}
 * {{schema.description | doxygenify}}
 {%-endif%}
 */
class {{Name}}
{
public:
    /*! Enumeration of possible values
     */
    enum class Value
    {
        {%-for opt in schema.enum %}
        {{opt |enumify}}{%if not loop.last%},{%endif%}
        {%-endfor%}
    };

    /*! The number of different values.
     * If this list corresponds to a list of values, it may be good to static_assert on the length of both lists
     */
    static constexpr int VALUE_ENUM_OPTION_COUNT = {{schema.enum | length}};
    {%-if schema.default is defined %}
    /*! This string represents the default JSON value.
     */
    static constexpr char DEFAULT_STRING[] = "{{schema.default}}";

    /*! This is the default enum value.
     * When the class is called with an empty constructor, this is the value that is used.
     */
    static constexpr Value DEFAULT_VALUE = Value::{{schema.default |enumify}};
    {%-endif%}

    /*! Constructor for {{Name}}.
     * \param value initial value
     */
    {{Name}}(Value value);
    {# #}
    {%-if schema.default is defined %}
    /*! Constructor that initializes the object with the {{schema.default |enumify}} value.
     */
    {{Name}}();
    {%-endif%}

    /*! Default destructor.
     */
    virtual ~{{Name}}() = default;

    /*! Getter operator.
     */
    operator Value() const;
    
    /*! Assignment operator.
     * \param value new value
     */
    {{Name}}& operator=(Value value);

    /*! Stream operator
     * \param os the output stream
     * \param v instance of {{Name}}
     */
    friend std::ostream& operator<<(std::ostream& os, const {{Name}}& v);

    /*! The less than comparison operator.
     * \param left A {{Name}} instance on the left size of the less than expression.
     * \param right A {{Name}} instance on the right side of the less than expression.
     * \return true if the less than expression is true.
     */
    friend bool operator< (const {{Name}}& left, const {{Name}}& right);

    /*! Produce a hash value of the object.
     * \param e A {{Name}} instance from which to produce a hash.
     * \return a hash number using a boost hashing algorithm.
     */
    friend std::size_t hash_value(const {{Name}}& e);

    /*! Sets the value to the provided enumerated Value.
     * \param value new value.
     */
    void Set(Value value);

    /*! Get the enumerated Value.
     */
    Value Get() const;

    /*! Returns the json string value for the enumerated value.
     * \param value is the value for which a string should be returned.
     */
    static std::string EnumToString(Value value);

    /*! Returns an enumerated value matching the provided string.
     * \param str is the string to match.
     * \throws std::out_of_range If the provided string does not match an enumerated value.
     */
    static Value StringToEnum(const std::string& str);

    /*! Initializes a {{Name}} object from JSON.
     * \param json JSON string value that maps to an enumerated value.
     * \throws {{exception}} If the JSON value isn't one of the supported string values.
     */
    static {{Name}} FromJson(const rapidjson::Value& json);

    /*! Initializes a {{Name}} object from a string value.
     * \param str must match one of the supported string values.
     * \throws {{exception}} if the provided value isn't a supported value.
     */
    static {{Name}} FromString(const std::string& str);

    /*! Returns a JSON string representation of this object.
     * \param value is modified with the JSON string representation.
     * \param allocator is the rapidjson allocator object from the parent document.
     */
    void ToJson(rapidjson::Value& value, rapidjson::Value::AllocatorType& allocator) const;

    /*! Returns a string representation of this object.
     * \return string representation without quotes.
     */
    std::string ToString() const;

    /*! Sets a string handle associated with this {{Name}} instance.
     * This gets called by a parent object after creating an instance that is used for an object's property.
     * \param handle is the string name.
     */
    void SetHandle(const std::string& handle);

    /*! Gets the string handle associated with this {{Name}} instance.
     * This is often the property name used in a JSON-object parent.
     * It may be empty.
     * \returns the handle string
     */
    std::string GetHandle() const;
private:
    Value _value;
    std::string _handle;
};